// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.core.editor.utils;

import java.util.ArrayList;
import java.util.List;

import org.dengues.core.CorePlugin;
import org.dengues.core.editor.AbstractEditorInput;
import org.dengues.core.prefs.IDenguesPrefsConstant;
import org.dengues.core.warehouse.ENodeCategoryName;
import org.eclipse.draw2d.FocusEvent;
import org.eclipse.draw2d.FocusListener;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.DefaultEditDomain;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.internal.ui.palette.editparts.DrawerEditPart;
import org.eclipse.gef.internal.ui.palette.editparts.DrawerFigure;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.ui.palette.PaletteEditPartFactory;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gef.ui.palette.PaletteViewerPreferences;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences;
import org.eclipse.gef.ui.parts.PaletteViewerKeyHandler;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

/**
 * Utility class for GEF components editor.
 * 
 * 
 * yzhang class global comment. Detailled comment <br/>
 * 
 * $Id: GEFEditorUtils.java 下午03:24:46 2007-10-26 +0000 (2007-10-26) yzhang $
 * 
 */
public class GEFEditorUtils {

    private static List<IEditorPart> editors = new ArrayList<IEditorPart>();

    /**
     * Register active editor.
     * 
     * yzhang Comment method "registActiveEditor".
     * 
     * @param editor
     */
    public static void registActiveEditor(IEditorPart editor) {
        editors.add(editor);
    }

    /**
     * Remove disposed editor.
     * 
     * yzhang Comment method "removeDisposedEditor".
     * 
     * @param editor
     */
    public static void removeDisposedEditor(IEditorPart editor) {
        editors.remove(editor);
    }

    /**
     * Return active editors.
     * 
     * yzhang Comment method "getActiveEditorParts".
     * 
     * @return
     */
    public static List<IEditorPart> getActiveEditorParts() {
        return editors;
    }

    /**
     * Return a FlyoutPreferences instance used to save/load the preferences of a flyout palette.
     */
    public static FlyoutPreferences createPalettePreferences() {
        return new FlyoutPreferences() {

            private IPreferenceStore getPreferenceStore() {
                return CorePlugin.getDefault().getPreferenceStore();
            }

            public int getDockLocation() {
                return getPreferenceStore().getInt(IDenguesPrefsConstant.PALETTE_DOCK_LOCATION);
            }

            public int getPaletteState() {
                return getPreferenceStore().getInt(IDenguesPrefsConstant.PALETTE_STATE);
            }

            public int getPaletteWidth() {
                return getPreferenceStore().getInt(IDenguesPrefsConstant.PALETTE_SIZE);
            }

            public void setDockLocation(int location) {
                getPreferenceStore().setValue(IDenguesPrefsConstant.PALETTE_DOCK_LOCATION, location);
            }

            public void setPaletteState(int state) {
                getPreferenceStore().setValue(IDenguesPrefsConstant.PALETTE_STATE, state);
            }

            public void setPaletteWidth(int width) {
                getPreferenceStore().setValue(IDenguesPrefsConstant.PALETTE_SIZE, width);
            }
        };
    }

    public static PaletteViewerProvider createPaletteViewerProvider(DefaultEditDomain defaultEditDomain) {
        return new GenericPaletteViewerProvider(defaultEditDomain);
    }

    static class GenericPaletteViewerProvider extends PaletteViewerProvider {

        EditDomain graphicalViewerDomain;

        public GenericPaletteViewerProvider(EditDomain graphicalViewerDomain) {
            super(graphicalViewerDomain);
            this.graphicalViewerDomain = graphicalViewerDomain;
        }

        @Override
        public PaletteViewer createPaletteViewer(Composite parent) {
            PaletteViewer pViewer = new GenericPaletteViewer(graphicalViewerDomain);
            pViewer.createControl(parent);
            configurePaletteViewer(pViewer);
            hookPaletteViewer(pViewer);
            pViewer.getPaletteViewerPreferences().setLayoutSetting(PaletteViewerPreferences.LAYOUT_COLUMNS);
            pViewer.getPaletteViewerPreferences().setUseLargeIcons(PaletteViewerPreferences.LAYOUT_COLUMNS, true);
            return pViewer;
        }
    }

    static class GenericPaletteViewer extends PaletteViewer {

        public GenericPaletteViewer(EditDomain graphicalViewerDomain) {
            setEditDomain(graphicalViewerDomain);
            setKeyHandler(new PaletteViewerKeyHandler(this));
            setEditPartFactory(new GenericPaletteEditPartFactory());
        }
    }

    static class GenericPaletteEditPartFactory extends PaletteEditPartFactory {

        protected EditPart createDrawerEditPart(EditPart parentEditPart, Object model) {
            return new GenericDrawerEditPart((PaletteDrawer) model);
        }

    }

    static class GenericDrawerEditPart extends DrawerEditPart {

        private int childLevel = 0;

        public GenericDrawerEditPart(PaletteDrawer drawer) {
            super(drawer);
        }

        public IFigure createFigure() {
            if (getParent() instanceof GenericDrawerEditPart) {
                GenericDrawerEditPart parent = (GenericDrawerEditPart) getParent();
                childLevel = parent.childLevel + 1;

                GenericDrawerFigure fig = new GenericDrawerFigure(getViewer().getControl(), childLevel) {

                    IFigure buildTooltip() {
                        return createToolTip();
                    }
                };
                fig.setExpanded(getDrawer().isInitiallyOpen());
                fig.setPinned(getDrawer().isInitiallyPinned());

                fig.getCollapseToggle().addFocusListener(new FocusListener.Stub() {

                    public void focusGained(FocusEvent fe) {
                        getViewer().select(GenericDrawerEditPart.this);
                    }
                });

                return fig;
            }
            return super.createFigure();
        }

        class GenericDrawerFigure extends DrawerFigure {

            private static final int COLOR_INCREMENT = 15;

            private static final int X_OFFSET = 17;

            public GenericDrawerFigure(Control control, int childLevel) {
                super(control);

                Color baseColor = control.getBackground();
                Color backgroundColor = new Color(Display.getCurrent(), getNewValue(baseColor.getRed(), childLevel), getNewValue(
                        baseColor.getGreen(), childLevel), getNewValue(baseColor.getBlue(), childLevel));
                getContentPane().setBackgroundColor(backgroundColor);
            }

            private int getNewValue(int oldValue, int childLevel) {
                int result = oldValue - childLevel * COLOR_INCREMENT;
                return (result > 0 ? result : 0);
            }

            @Override
            public Rectangle getBounds() {
                return new Rectangle(bounds.x + X_OFFSET, bounds.y, bounds.width, bounds.height);
            }
        }
    }

    private static List<String> getOpenedEditors() {
        List<String> list = new ArrayList<String>();
        IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (activeWorkbenchWindow != null) {
            IWorkbenchPage activePage = activeWorkbenchWindow.getActivePage();
            if (activePage != null) {
                IEditorReference[] editorReferences = activePage.getEditorReferences();
                if (editorReferences != null) {
                    for (IEditorReference editorReference : editorReferences) {
                        try {
                            IEditorInput editorInput = editorReference.getEditorInput();
                            if (editorInput instanceof AbstractEditorInput) {
                                list.add(((AbstractEditorInput) editorInput).getEditorUniqueName());
                            }
                        } catch (PartInitException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            }
        }
        return list;
    }

    public static boolean isNodeActived(String objName, ENodeCategoryName name) {
        return getOpenedEditors().contains(getEditorUniqueName(objName, name));
    }

    public static String getEditorUniqueName(String objName, ENodeCategoryName name) {
        return name.getName() + name.getVersion() + objName;
    }
}
